package com.gmail.at.service.jpa;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.gmail.at.dao.ScheduleDAO;
import com.gmail.at.dao.StationDAO;
import com.gmail.at.dao.TrainDAO;
import com.gmail.at.model.Schedule;
import com.gmail.at.model.Station;
import com.gmail.at.model.Train;
import com.gmail.at.service.ScheduleService;
import com.google.common.collect.Lists;

@Service("scheduleService")
@Repository
@Transactional
public class ScheduleServiceImpl implements ScheduleService {

	final Logger logger = LoggerFactory.getLogger(ScheduleService.class);

	@Autowired
	private ScheduleDAO scheduleDAO;

	@Autowired
	private StationDAO stationDAO;

	@Autowired
	private TrainDAO trainDAO;

	@PersistenceContext
	private EntityManager em;

	@Override
	@Transactional(readOnly = true)
	public List<Schedule> findAll() {
		return Lists.newArrayList(scheduleDAO.findAll());
	}

	@Override
	@Transactional(readOnly = true)
	public Schedule findById(Integer id) {
		return scheduleDAO.findOne(id);
	}

	@Override
	public String save(Schedule schedule) {
		Train train = trainDAO.findByNumber(schedule.getTrain()
				.getTrainNumber());
		if (train == null) {
			return "Invalid train information, no such train number in database";
		}
		Station station1 = stationDAO.findByName(schedule.getStation1()
				.getStationName());
		if (station1 == null) {
			return "Invalid departure station information, no such station name in database";
		}
		Station station2 = stationDAO.findByName(schedule.getStation2()
				.getStationName());
		if (station2 == null) {
			return "Invalid departure station information, no such station name in database";
		}
		List<Schedule> sched = scheduleDAO.findIsSchedulePossible(train,
				schedule.getDateOfDeparture(), schedule.getDateOfArrival());
		if (sched != null) {
			if (!sched.isEmpty()) {
				return "The train already has schedule in this time period";
			}		
		}
		schedule.setTrain(train);
		schedule.setStation1(station1);
		schedule.setStation2(station2);
		schedule.setDateOfArrival(schedule.getDateOfArrival());
		schedule.setDateOfDeparture(schedule.getDateOfDeparture());
		if (scheduleDAO.save(schedule) != null) {
			return "ok";
		}
		return "Some problems";
	}

	public String delete(Integer id) {
		Schedule schedule = this.findById(id);
		if (schedule != null) {
			scheduleDAO.delete(schedule);
			return "ok";
		}
		return "no";
	}

	@Override
	@Transactional(readOnly = true)
	public List<Schedule> searchSchedule(Station beginStation,
			Station endStation, DateTime beginTime) {
		logger.info(beginTime.toString());
		DateTime nextDay = beginTime;
		DateTime now = DateTime.now();
		nextDay = nextDay.plusDays(1);
		logger.info(nextDay.toString());
		beginStation = stationDAO.findByName(beginStation.getStationName());
		endStation = stationDAO.findByName(endStation.getStationName());
		List<Schedule> schedules = em.createNamedQuery("Schedule.searchSchedule", Schedule.class)
				.setParameter("departure", beginStation)
				.setParameter("arrival", endStation)
				.setParameter("dateBegin", beginTime)
				.setParameter("next", nextDay).setParameter("now", now)
				.getResultList();
		for (Schedule s: schedules) {
			s.setSearchDate("" + (s.getTrain().getPlaces() - s.getTickets().size()));
		}
		return schedules;
	}

	@Override
	public Page<Schedule> findAllByPage(Pageable pageable) {
		return scheduleDAO.findAll(pageable);
	}

	@Override
	public String update(Schedule temp, Schedule schedule) {
		Train train = trainDAO.findByNumber(schedule.getTrain()
				.getTrainNumber());
		if (train == null) {
			return "Invalid train information, no such train number in database";
		}
		Station station1 = stationDAO.findByName(schedule.getStation1()
				.getStationName());
		if (station1 == null) {
			return "Invalid departure station information, no such station name in database";
		}
		Station station2 = stationDAO.findByName(schedule.getStation2()
				.getStationName());
		if (station2 == null) {
			return "Invalid departure station information, no such station name in database";
		}
		List<Schedule> sched = scheduleDAO.findIsSchedulePossible(train, schedule.getDateOfDeparture(), schedule.getDateOfArrival());
		if (sched != null) {
			if (!sched.isEmpty()) {
				if (sched.size() != 1) {
					return "The train already has schedule in this time period";
				}
				if (sched.get(0) != temp) {
					return "The train already has schedule in this time period";
				}
			}		
		}
		temp.setTrain(train);
		temp.setStation1(station1);
		temp.setStation2(station2);
		temp.setDateOfArrival(schedule.getDateOfArrival());
		temp.setDateOfDeparture(schedule.getDateOfDeparture());
		if (scheduleDAO.save(temp) != null) {
			return "ok";
		}
		return "Some problems";
	}

}
